home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / gus / miditest.zip / MIDITEST.CPP next >
C/C++ Source or Header  |  1993-03-28  |  7KB  |  316 lines

  1. /* Gravis Ultrasound MIDI port test program */
  2. /* Copyright 1993 Dave Perry */
  3. /* This program may be used for non-commercial purposes only */
  4.  
  5. #include <dos.h>
  6. #include <stdio.h>
  7. #include <conio.h>
  8. #include <stdlib.h>
  9.  
  10. #pragma inline
  11.  
  12. #define CONTROL 0x100      /* Control port offset         */
  13. #define DATA    0x101      /* Data port offset             */
  14. #define BUFSIZE 512        /* Ring buffer                 */
  15. #define PIC_MASK 0x21      /* 8259 interrupt mask port     */
  16. #define PIC_MASK2 0xa1     /* Secondary 8259 mask port     */
  17.  
  18.  
  19. unsigned char buffer[BUFSIZE];
  20. unsigned char *head = buffer;
  21. unsigned char *tail = buffer;
  22.  
  23. unsigned int base; /* Card base address */
  24.  
  25. void interrupt ( *old_isr)(...);
  26.  
  27. /*
  28. status byte   meaning        data bytes
  29.  
  30. 0x80-0x8f     note off       2 - 1 byte pitch, followed by 1 byte velocity
  31. 0x90-0x9f     note on        2 - 1 byte pitch, followed by 1 byte velocity
  32. 0xa0-0xaf     key pressure   2 - 1 byte pitch, 1 byte pressure (after-touch)
  33. 0xb0-0xbf     parameter      2 - 1 byte parameter number, 1 byte setting
  34. 0xc0-0xcf     program        1 byte program selected
  35. 0xd0-0xdf     chan. pressure 1 byte channel pressure (after-touch)
  36. 0xe0-0xef     pitch wheel    2 bytes gives a 14 bit value, least significant
  37.                    7 bits first
  38. */
  39.  
  40. enum status_t  {UNKNOWN = 0,
  41.                 NOTE_OFF = 0x80,
  42.                 NOTE_ON  = 0x90,
  43.                 KEY_PRES = 0xa0,
  44.                 PARM     = 0xb0,
  45.                 PROGRAM  = 0xc0,
  46.                 CHAN_PRES= 0xd0,
  47.                 PITCH    = 0xe0,
  48.                 SYSEX    = 0xf0};
  49.  
  50. char *keyname[] = {
  51.     "C  ",
  52.     "C# ",
  53.     "D  ",
  54.     "D# ",
  55.     "E  ",
  56.     "F  ",
  57.     "F# ",
  58.     "G  ",
  59.     "G# ",
  60.     "A  ",
  61.     "A# ",
  62.     "B  "
  63. };
  64.  
  65.  
  66. void decode(unsigned char *message)
  67. {
  68.  
  69.     printf("| ");
  70.     if((message[0] & 0xf0) != SYSEX)
  71.         printf("Ch.%-2d ",(message[0] & 0x0f) + 1);
  72.     switch(message[0] & 0xf0){
  73.         case UNKNOWN:
  74.             printf("Unknown message");
  75.             break;
  76.         case NOTE_OFF:
  77.             printf("Note Off  %d%s Vel: %d",
  78.                 message[1]/12,keyname[message[1] % 12],message[2]);
  79.             break;
  80.         case NOTE_ON:
  81.             printf("Note On   %d%s Vel: %d",
  82.                 message[1]/12,keyname[message[1] % 12],message[2]);
  83.             break;
  84.         case KEY_PRES:
  85.             printf("Key Pres. %d%s Pressure: %d",
  86.                 message[1]/12,keyname[message[1] % 12],message[2]);
  87.             break;
  88.         case PARM:
  89.             printf("Parameter %d Setting: %d",message[1],message[2]);
  90.             break;
  91.         case PROGRAM:
  92.             printf("Program   %d",message[1]);
  93.             break;
  94.         case CHAN_PRES:
  95.             printf("Ch Press. %d",message[1]);
  96.             break;
  97.         case PITCH:
  98.             printf("P. Wheel  %d",(message[1]+(message[2] << 7)) - 8192);
  99.             break;
  100.         case SYSEX:
  101.             printf("System");
  102.             break;
  103.         default:
  104.             ;
  105.     }
  106. }
  107.  
  108. void
  109. showbyte(unsigned char abyte)
  110. {
  111.     static status_t cur_status = UNKNOWN;
  112.     static int arg_cnt = 0;
  113.     static unsigned char message[3];
  114.  
  115.     if(abyte & 0x80) {                 /* It's a status byte */
  116.         if((abyte < 0xf8)){          /* Ignore "real time" bytes */
  117.             printf("\n%2x ",abyte);     /* Start new line, print status byte */
  118.             cur_status = (status_t)(abyte & 0xf0);
  119.             message[0] = abyte;
  120.             arg_cnt = 0;
  121.         }
  122.     } else {           /* Not a status byte */
  123.         switch(cur_status) {
  124.             case UNKNOWN:
  125.             case NOTE_OFF:
  126.             case NOTE_ON:
  127.             case KEY_PRES:
  128.             case PARM:
  129.             case PITCH:
  130.             case SYSEX:
  131.                 if((++arg_cnt % 2) && (arg_cnt != 1))
  132.                     printf("\n   %02x ",abyte);
  133.                 else
  134.                     printf("%02x ",abyte);
  135.                 if((arg_cnt + 1) % 2) {
  136.                     message[2] = abyte;
  137.                     decode(message);
  138.                 } else
  139.                     message[1] = abyte;
  140.  
  141.  
  142.                 break;
  143.             case PROGRAM:
  144.             case CHAN_PRES:
  145.                 if(arg_cnt++)
  146.                     printf("\n   %02x    ");
  147.                 else
  148.                     printf("%02x    ",abyte);
  149.                 message[1] = abyte;
  150.                 decode(message);
  151.                 break;
  152.         } /* switch */
  153.     } /* else */
  154. }
  155.  
  156. void
  157. send_eoi()
  158. {
  159.     asm mov    al,0bh;        /* read in-service register from */
  160.     asm out    0a0h,al;    /* secondary 8259 */
  161.     asm nop;            /* settling delay */
  162.     asm nop
  163.     asm nop
  164.     asm in    al,0a0h;    /* get it */
  165.     asm or    al,al;      /* Any bits set? */
  166.     asm jz    lab1;       /* nope, not a secondary interrupt */
  167.     asm mov    al,20h;     /* Get EOI instruction */
  168.     asm out    0a0h,al;    /* Secondary 8259 */
  169. lab1:    asm mov    al,20h; /* 8259 end-of-interrupt command */
  170.     asm out    20h,al;     /*  Primary 8259 */
  171. }
  172.  
  173.  
  174. /* MIDI input interrupt handler */
  175. void interrupt
  176. midi_isr(...)
  177. {
  178.     static cnt = 0;
  179.  
  180.     *head = inportb(base+DATA);  /* Grab the data */
  181.     asm cli;
  182.     if(cnt == BUFSIZE - 1) {/* Adjust the buffer pointer */
  183.         cnt = 0;
  184.         head = buffer;
  185.     } else {
  186.         ++head;
  187.         ++cnt;
  188.     }
  189.     asm sti;
  190.     send_eoi();
  191. }
  192.  
  193. /* Pull a byte from the buffer */
  194. unsigned char
  195. pullbyte(void)
  196. {
  197.     static cnt = 0;
  198.     unsigned char retval;
  199.  
  200.     asm cli;                /* Ints off for pointer manipulation */
  201.     if (head != tail)
  202.     {
  203.         retval = *tail++;
  204.         cnt++;
  205.         if(cnt == BUFSIZE) {
  206.             cnt = 0;
  207.             tail = buffer;
  208.         }
  209.     }
  210.     asm sti;
  211.     return(retval);
  212. }
  213.  
  214. void
  215. hook_irq(unsigned char irq)
  216. {
  217.     unsigned char abyte,int_mask,vector;
  218.     unsigned int pic_mask; /* Address of PIC mask */
  219.  
  220.     if(irq < 8){
  221.         vector = irq + 8;
  222.         pic_mask = PIC_MASK;
  223.         int_mask = 1 << irq;
  224.     }
  225.     else {
  226.         vector = irq + 0x70 - 8;
  227.         pic_mask = PIC_MASK2;
  228.         int_mask = 1 << (irq - 8);
  229.     }
  230.  
  231.  
  232.     /* save the existing interrupt vector */
  233.     old_isr = getvect(vector);
  234.  
  235.     /* Install our interrupt vector */
  236.     setvect(vector,midi_isr);
  237.  
  238.     /* Enable interrupts on the MIDI UART */
  239.     outportb(base+CONTROL,0x95);
  240.  
  241.     /* Set up the 8259 PIC chip */
  242.     abyte = inportb(pic_mask); /* Read 8259 mask */
  243.     abyte &= ~int_mask;        /* Clear mask for desired IRQ */
  244.     outportb(pic_mask,abyte);
  245.  
  246. }
  247.  
  248. void
  249. unhook_irq(unsigned char irq)
  250. {
  251.  
  252.     unsigned char abyte, int_mask, vector;
  253.     unsigned int pic_mask;
  254.  
  255.     if(irq < 8){
  256.         vector = irq + 8;
  257.         pic_mask = PIC_MASK;
  258.         int_mask = 1 << irq;
  259.     }
  260.     else {
  261.         vector = irq + 0x70 - 8;
  262.         pic_mask = PIC_MASK2;
  263.         int_mask = 1 << (irq - 8);
  264.     }
  265.  
  266.     /* Mask the interrupt we hooked */
  267.     abyte = inportb(pic_mask); /* Read 8259 mask */
  268.     abyte |= int_mask;         /* Set mask for desired IRQ */
  269.     outportb(pic_mask,abyte);
  270.  
  271.     /* Restore old interrupt handler */
  272.     setvect(vector,midi_isr);
  273. }
  274.  
  275. main()
  276. {
  277.     int abyte;
  278.     char *envstring;
  279.     unsigned int midi_irq,dummy;
  280.  
  281.     envstring = getenv("ULTRASND");
  282.     if(envstring == NULL) {
  283.         printf("ULTRASND environment string not found\n");
  284.         printf("Check your Ultrasound setup\n");
  285.         exit(0);
  286.     }
  287.     sscanf(envstring,"%x,%d,%d,%d,%d",
  288.         &base,&dummy,&dummy,&dummy,&midi_irq);
  289.  
  290.     hook_irq(midi_irq);
  291.  
  292.     printf("\nGravis Ultrasound MIDI Tester V1.0");
  293.     printf("\nCopyright 1993 Dave Perry");
  294.  
  295.     printf("\nYour current setup is Base = %x, MIDI IRQ = %d",base,midi_irq);
  296.     printf("\nReading MIDI input - press any key to exit\n");
  297.  
  298.     while (!kbhit()){
  299.         if(head != tail) { /* If new byte available */
  300.             abyte = pullbyte();
  301.  
  302.             /* MIDI Thru */
  303.             while(!(inportb(base+CONTROL) & 0x02))
  304.                 ;
  305.             outportb(base+DATA,abyte);
  306.  
  307.             showbyte(abyte);
  308.  
  309.         }
  310.     }
  311.     printf("\n");
  312.  
  313.     unhook_irq(midi_irq);
  314.     return 0;
  315. }
  316.